/******************************************************************************* 
  Copyright (C), 1988-2020, zeno Tech. Co., Ltd.
  Description:   VIDEO模块  
  Function List:     
  History:
    <huangzhendi -- 2014-09-26>  创建
*******************************************************************************/ 

/*=============================================================================
                                 Includes                                  
 =============================================================================*/
#include "videoPriv.h"
#include "videoIsp.h"
//#include "videoHiVin.h"
//#include "videoHiVpss.h"
#include "StreamComposeMgr.h"


/*=============================================================================
                               Macro Definition
 =============================================================================*/
    
#define LT9611_DEV_NAME "lt9611"
#define LT9611_IOCTL_BASE      'A'    
#define LT9611_GET_HDMI       _IOR(LT9611_IOCTL_BASE, 0, LT9611_cmdArgs_t)
#define LT9611_ENABLE_HDMI    _IOR(LT9611_IOCTL_BASE, 1, LT9611_cmdArgs_t)
#define LT9611_DISABLE_HDMI   _IOR(LT9611_IOCTL_BASE, 2, LT9611_cmdArgs_t)
#define LT9611_CEC_STANDBY    _IOR(LT9611_IOCTL_BASE, 3, LT9611_cmdArgs_t)
#define LT9611_CEC_IMAGEON    _IOR(LT9611_IOCTL_BASE, 4, LT9611_cmdArgs_t)


#define HDMI_ENABLE /* hdmi or sdi */

/*=============================================================================
                        Local Structures and Typedef 
 =============================================================================*/
typedef struct 
{
   union
   {
       int hdmiStatus;
   };
} LT9611_cmdArgs_t;

/*=============================================================================
                             Extern Variables                                  
=============================================================================*/
#define VIDEO_SYS_ALIGN_WIDTH    64     /* mpp缓存字节对齐 */
#define VI_PROC_FILE             "/proc/umap/vi"      /* vi proc文件 */
#define VI_MIN_INT               10     /* vi允许的最小正常中断 */
#define VI_STATUS_BUF_LEN        (1024*4)

#define MIPI_DEV_NODE            "/dev/hi_mipi"


#define DIR_DEV_NAME "dir_sensor"
#define DIR_IOCTL_BASE      'A'

#define DIR_GET_ACCEL           _IOR(DIR_IOCTL_BASE, 0, DIR_cmdArgs_t)

#define USB_DWC3_PATH "/proc/dwc3/4110000.hidwc3_0/csts"


typedef struct 
{ 
    union
    {
        short accel_short[3];
    };
} DIR_cmdArgs_t;

/*=============================================================================
                             Local Variables                                  
 =============================================================================*/
VIDEO_ctl_t videoCtl_g;

static int hasCreated_s = 0;

static int hdmioutFd_s = -1;

/*=============================================================================
                            Extern Function Definition                                  
 =============================================================================*/
extern int AUDIO_Init(void);

/*=============================================================================
                             Function Definition                                  
 =============================================================================*/ 
int HdmiIsEnable()
{
    int iRet =0;
    int HdmiIsEnable = 0;

    if( VIDEO_PlayStatus())
    {
        HdmiIsEnable = 1;
    }
    else
    {
        HdmiIsEnable = 0;
    }

    return HdmiIsEnable;
}

/*******************************************************************************
  Function:     VIDEO_GetPicSize
  Description:  根据图像分辨率获取图像尺寸
  Input:        - standard: 制度
                - resolution: 图像分辨率
                - bRotate: 是否旋转
  Output:       - pPicSize: 图像尺寸
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
int VIDEO_GetPicSize(VIDEO_standard_t standard, 
                     VIDEO_resolution_t resolution, 
                     VIDEO_picSize_t *pPicSize,
                     int bRotate)
{
    int tmpWidth;
    
    switch (resolution)
    {
        case VIDEO_RESOLUTION_960_540:
            pPicSize->u32Width = 960;
            pPicSize->u32Height = 540;
            break;
        case VIDEO_RESOLUTION_640_360:
            pPicSize->u32Width = 640;
            pPicSize->u32Height = 360;
            break;
        case VIDEO_RESOLUTION_QCIF:
            pPicSize->u32Width = 176;
            pPicSize->u32Height = (VIDEO_STANDARD_PAL == standard)?144:120;
            break;
        case VIDEO_RESOLUTION_CIF:
            pPicSize->u32Width = 352;
            pPicSize->u32Height = 288;
            break;
        case VIDEO_RESOLUTION_D1:
            pPicSize->u32Width = 704;
            pPicSize->u32Height = (VIDEO_STANDARD_PAL == standard)?576:480;
            break;
        case VIDEO_RESOLUTION_STD_D1:
            pPicSize->u32Width = 720;
            pPicSize->u32Height = (VIDEO_STANDARD_PAL == standard)?576:480;
            break;
        case VIDEO_RESOLUTION_960H:
            pPicSize->u32Width = 960;
            pPicSize->u32Height = (VIDEO_STANDARD_PAL == standard)?576:480;
            break;            
        case VIDEO_RESOLUTION_2CIF:
            pPicSize->u32Width = 360;
            pPicSize->u32Height = (VIDEO_STANDARD_PAL == standard)?576:480;
            break;
        case VIDEO_RESOLUTION_QVGA:    /* 320 * 240 */
            pPicSize->u32Width = 320;
            pPicSize->u32Height = 240;
            break;
        case VIDEO_RESOLUTION_VGA:     /* 640 * 480 */
            pPicSize->u32Width = 640;
            pPicSize->u32Height = 480;
            break;
        case VIDEO_RESOLUTION_XGA:     /* 1024 * 768 */
            pPicSize->u32Width = 1024;
            pPicSize->u32Height = 768;
            break;
        case VIDEO_RESOLUTION_SXGA:    /* 1400 * 1050 */
            pPicSize->u32Width = 1400;
            pPicSize->u32Height = 1050;
            break;
        case VIDEO_RESOLUTION_UXGA:    /* 1600 * 1200 */
            pPicSize->u32Width = 1600;
            pPicSize->u32Height = 1200;
            break;
        case VIDEO_RESOLUTION_QXGA:    /* 2048 * 1536 */
            pPicSize->u32Width = 2048;
            pPicSize->u32Height = 1536;
            break;
        case VIDEO_RESOLUTION_WVGA:    /* 854 * 480 */
            pPicSize->u32Width = 854;
            pPicSize->u32Height = 480;
            break;
        case VIDEO_RESOLUTION_WSXGA:   /* 1680 * 1050 */
            pPicSize->u32Width = 1680;
            pPicSize->u32Height = 1050;
            break;
        case VIDEO_RESOLUTION_WUXGA:   /* 1920 * 1200 */
            pPicSize->u32Width = 1920;
            pPicSize->u32Height = 1200;
            break;
        case VIDEO_RESOLUTION_WQXGA:   /* 2560 * 1600 */
            pPicSize->u32Width = 2560;
            pPicSize->u32Height = 1600;
            break;
        case VIDEO_RESOLUTION_H720:   /* 1280 * 720 */
            pPicSize->u32Width = 1280;
            pPicSize->u32Height = 720;
            break;
        case VIDEO_RESOLUTION_H1080:  /* 1920 * 1080 */
            pPicSize->u32Width = 1920;
            pPicSize->u32Height = 1080;
            break;
        case VIDEO_RESOLUTION_H960:  /* 1280 * 960 */
            pPicSize->u32Width = 1280;
            pPicSize->u32Height = 960;
            break;    
        case VIDEO_RESOLUTION_H1024:  /* 1280 * 1024 */
            pPicSize->u32Width = 1280;
            pPicSize->u32Height = 1024;
            break;  
        case VIDEO_RESOLUTION_H1920:  /* 2560 * 1920 */
            pPicSize->u32Width  = 2560;
            pPicSize->u32Height = 1920;
            break;
        case VIDEO_RESOLUTION_2592_1944:
            pPicSize->u32Width  = 2592;
            pPicSize->u32Height = 1944;
            break;
		case VIDEO_RESOLUTION_H1536:  /* 2048 * 1536 */
            pPicSize->u32Width = 2048;
            pPicSize->u32Height = 1536;
            break;
		case VIDEO_RESOLUTION_H1520:  /* 2048 * 1520 */
            pPicSize->u32Width = 2048;
            pPicSize->u32Height = 1520;
            break;
		case VIDEO_RESOLUTION_4M:  /* 2592 * 1536 */
            pPicSize->u32Width = 2592;
            pPicSize->u32Height = 1536;
            break;
   		case VIDEO_RESOLUTION_2560_1440:  /* 2560 * 1440 */
            pPicSize->u32Width = 2560;
            pPicSize->u32Height = 1440;
            break;
   		case VIDEO_RESOLUTION_2304_1296:  /* 2304 * 1296 */
            pPicSize->u32Width = 2304;
            pPicSize->u32Height = 1296;
            break;
   		case VIDEO_RESOLUTION_ALG4_3:  /* 800 * 600 */
            pPicSize->u32Width = 800;
            pPicSize->u32Height = 600;
            break;
   		case VIDEO_RESOLUTION_ALG16_9:  /* 1024 * 576 */
            pPicSize->u32Width = 1024;
            pPicSize->u32Height = 576;
            break;
        case VIDEO_RESOLUTION_4096_2160:  /* 4096 * 2160 */
            pPicSize->u32Width = 4096;
            pPicSize->u32Height = 2160;
            break;
        case VIDEO_RESOLUTION_3840_2160:  /* 3840 * 2160 */
            pPicSize->u32Width = 3840;
            pPicSize->u32Height = 2160;
            break;
        case VIDEO_RESOLUTION_4000_3000:  /* 4000 * 3000 */
            pPicSize->u32Width = 4000;
            pPicSize->u32Height = 3000;
            break;
		case VIDEO_RESOLUTION_1792_980:  /* 1792 * 980 */
            pPicSize->u32Width = 1792;
            pPicSize->u32Height = 980;
            break;
        case VIDEO_RESOLUTION_1792_1080:
            pPicSize->u32Width = 1792;
            pPicSize->u32Height = 1080;
            break;
        default:
            LOG_PrintError("resolution %d is invalid!\n", resolution);
            return -1;
    }

    if (bRotate)
    {
        tmpWidth = pPicSize->u32Width;
        pPicSize->u32Width = pPicSize->u32Height;
        pPicSize->u32Height = tmpWidth;
    }
    
    return 0;
}


/*******************************************************************************
  Function:     VIDEO_GetResolution
  Description:  根据宽高获取分辨率类型
  Input:        - picSize: 图像尺寸
                - bRotate: 是否发生旋转
                - standard: 图像制式
  Output:       - pResolution: 分辨率类型
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
int VIDEO_GetResolution(VIDEO_picSize_t *pPicSize, 
                        int bRotate, 
                        VIDEO_standard_t standard,
                        VIDEO_resolution_t *pResolution)
{
    unsigned int tmpWidth;

    if (bRotate)
    {
        tmpWidth = pPicSize->u32Width;
        pPicSize->u32Width = pPicSize->u32Height;
        pPicSize->u32Height = tmpWidth;
    }

    if (pPicSize->u32Width == 1920 && pPicSize->u32Height == 1080)
    {
        *pResolution = VIDEO_RESOLUTION_H1080;
    }
    else if (pPicSize->u32Width == 2048 && pPicSize->u32Height == 1536)
    {
        *pResolution = VIDEO_RESOLUTION_H1536;
    }
    else if (pPicSize->u32Width == 2048 && pPicSize->u32Height == 1520)
    {
        *pResolution = VIDEO_RESOLUTION_H1520;
    }
    else if (pPicSize->u32Width == 2304 && pPicSize->u32Height == 1296)
    {
        *pResolution = VIDEO_RESOLUTION_2304_1296;
    }
    else if (pPicSize->u32Width == 2592 && pPicSize->u32Height == 1536)
    {
        *pResolution = VIDEO_RESOLUTION_4M;
    }
    else if (pPicSize->u32Width == 2560 && pPicSize->u32Height == 1440)
    {
        *pResolution = VIDEO_RESOLUTION_2560_1440;
    }
    else if (pPicSize->u32Width == 2560 && pPicSize->u32Height == 1920)
    {
        *pResolution = VIDEO_RESOLUTION_H1920;
    }
    else if (pPicSize->u32Width == 2592 && pPicSize->u32Height == 1944)
    {
        *pResolution = VIDEO_RESOLUTION_2592_1944;
    }
    else if (pPicSize->u32Width == 1280 && pPicSize->u32Height == 720)
    {
        *pResolution = VIDEO_RESOLUTION_H720;
    }
    else if (pPicSize->u32Width == 1280 && pPicSize->u32Height == 960)
    {
        *pResolution = VIDEO_RESOLUTION_H960;
    }
    else if (pPicSize->u32Width == 704 
                  && (pPicSize->u32Height == 576 || pPicSize->u32Height == 480))
    {
        *pResolution = VIDEO_RESOLUTION_D1;
    }
    else if (pPicSize->u32Width == 4096 && pPicSize->u32Height == 2160)
    {
        *pResolution = VIDEO_RESOLUTION_4096_2160;
    }
    else if (pPicSize->u32Width == 3840 && pPicSize->u32Height == 2160)
    {
        *pResolution = VIDEO_RESOLUTION_3840_2160;
    }
    else if (pPicSize->u32Width == 4000 && pPicSize->u32Height == 3000)
    {
        *pResolution = VIDEO_RESOLUTION_4000_3000;
    }
	else if (pPicSize->u32Width == 1792 && pPicSize->u32Height == 980)
    {
        *pResolution = VIDEO_RESOLUTION_1792_980;
    }
	else if (pPicSize->u32Width == 1792 && pPicSize->u32Height == 1080)
    {
        *pResolution = VIDEO_RESOLUTION_1792_1080;
    }
    else if (pPicSize->u32Width == 640 && pPicSize->u32Height == 360)
    {
        *pResolution = VIDEO_RESOLUTION_640_360;
    }

    else
    {
        LOG_PrintError("width:%d, height:%d isn't support!\n", pPicSize->u32Width,
                                                               pPicSize->u32Height);
        return -1;
    }

    return 0;
}

#if 0

/*******************************************************************************
  Function:     VIDEO_GetVbConfg
  Description:  获取视频缓存池属性配置
  Input:        无
  Output:       - pVbConf: 视频缓存池属性指针
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
static int VIDEO_GetVbConfg(VB_CONFIG_S *pVbConf)
{

    int i, j;
    VIDEO_picSize_t picSize;
	PIXEL_FORMAT_E fmt;
	HI_U64 u64BlkSize;
    cJSON *pJson, *pSubJson, *pItem, *pSubItem;
    HI_U32 num=0;
    HI_U32 cnt[16]={0};
    VIDEO_resolution_t res[16]={0};
    int resolutionNum;
    int resolution;

    pJson = CFG_GetItem(NULL, "videoCfg.vb");
    if (pJson)
    {
        resolutionNum = cJSON_GetArraySize(pJson);
		for (i=0; i<resolutionNum; i++)
		{
            pSubJson = cJSON_GetArrayItem(pJson, i);
            pItem = cJSON_GetObjectItem(pSubJson, "resolution");
            resolution = pItem->valueint;
            if (resolution != videoCtl_g.resolution)
            {
                continue;
            }

            pSubItem = cJSON_GetObjectItem(pSubJson, "vbTbl");
                
            num = cJSON_GetArraySize(pSubItem);
    		for (j=0; j<num; j++)
    		{
    			pSubJson = cJSON_GetArrayItem(pSubItem, j);

    			pItem = cJSON_GetObjectItem(pSubJson, "resolution");
    			res[j] = pItem->valueint;

    			pItem = cJSON_GetObjectItem(pSubJson, "cnt");
    			cnt[j] = pItem->valueint;
    		}

            break;
		}

        if (i == resolutionNum)
        {
            LOG_PrintError("Fail to get resolution %d vbTbl!\n",
                            videoCtl_g.resolution);
        }
    } 
    
    memset(pVbConf,0,sizeof(VB_CONFIG_S));
    pVbConf->u32MaxPoolCnt = 32;

    for (i=0, j=0; i<num; i++)
    {
        if (cnt[i] == 0)
        {
            continue;
        }

        fmt = PIXEL_FORMAT_YVU_SEMIPLANAR_420;

		VIDEO_GetPicSize(videoCtl_g.standard, res[i], &picSize, 0);

		picSize.u32Width = VIDEO_ALIGN_UP(picSize.u32Width, DEFAULT_ALIGN);
		picSize.u32Height = VIDEO_ALIGN_UP(picSize.u32Height, DEFAULT_ALIGN);

        u64BlkSize = COMMON_GetPicBufferSize(picSize.u32Width, 
        						             picSize.u32Height,
        						             fmt,
        						         #if defined(HI3559AV100)
        						             DATA_BITWIDTH_10,
        						             COMPRESS_MODE_NONE,
        						             VIDEO_SYS_ALIGN_WIDTH
        						         #elif (defined(HI3516CV500) || defined(HI3516EV200) || defined(HI3519AV100))
										 	 DATA_BITWIDTH_8,
        						             COMPRESS_MODE_NONE,
        						             DEFAULT_ALIGN
        						         #endif
										 	 );

        
        pVbConf->astCommPool[j].u64BlkSize = u64BlkSize;
        pVbConf->astCommPool[j].u32BlkCnt = cnt[i]; 
        j++;
    } 
 
    return 0;
}
#endif  

/*******************************************************************************
  Function:     VIDEO_IspInit
  Description:  创建isp接口并初始化
  Input:        无
  Output:       无
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
static int VIDEO_IspInit(void)
{
	int ret;
	VIDEOISP_desc_t ispDesc;
	VIDEOISP_ctl_t *pVideoIsp;
	VIDEOISP_funcInit_t funcInit;
	VIDEO_lenInfo_t *pLenInfo;
	
	ispDesc.channel = 0;
	ret = VIDEOISP_CreateEx(&ispDesc, &videoCtl_g.pVideoIsp);
	if (ret)
	{
		LOG_PrintError("VIDEOISP_Create failed!\n");
		return -1;
	}

	pVideoIsp = videoCtl_g.pVideoIsp;

	if (!pVideoIsp->pFuncInit || !pVideoIsp->pGetLenInfo || !pVideoIsp->pFuncStart)
	{
		LOG_PrintError("isp function is NULL!\n");
		return -1;
	}

	funcInit.ispMode = VIDEOISP_MODE_COMM;
	funcInit.pLenName = videoCtl_g.lenName;
	funcInit.standard = videoCtl_g.standard;
	funcInit.resolution = videoCtl_g.resolution;
	funcInit.snsType = videoCtl_g.snsType;
	funcInit.fps = videoCtl_g.fps;

	if (videoCtl_g.wdrEnable)
	{
		funcInit.wdrMode = videoCtl_g.wdrMode;
	}
	else
	{
		funcInit.wdrMode = VIDEO_WDR_MODE_NONE;
	}

	ret = pVideoIsp->pFuncInit(pVideoIsp, &funcInit);
	if (ret)
	{
		LOG_PrintError("pVideoIsp->pFuncInit failed!\n");
		return -1;
	}

	ret = pVideoIsp->pFuncStart(pVideoIsp);
	if (ret)
	{
		LOG_PrintError("pVideoIsp->pFuncStart failed!\n");
		return -1;
	}

	if (1)
	{
	    ispDesc.channel = 1;
    	ret = VIDEOISP_CreateEx(&ispDesc, &videoCtl_g.pVideoSecIsp);
    	if (ret)
    	{
    		LOG_PrintError("VIDEOISP_Create failed!\n");
    		return -1;
    	}

    	pVideoIsp = videoCtl_g.pVideoSecIsp;

    	if (!pVideoIsp->pFuncInit || !pVideoIsp->pGetLenInfo || !pVideoIsp->pFuncStart)
    	{
    		LOG_PrintError("isp function is NULL!\n");
    		return -1;
    	}

    	funcInit.ispMode = VIDEOISP_MODE_COMM;
    	funcInit.pLenName = videoCtl_g.lenName;
    	funcInit.standard = videoCtl_g.standard;
    	funcInit.resolution = videoCtl_g.resolution;
    	funcInit.snsType = videoCtl_g.snsType;
    	funcInit.fps = videoCtl_g.fps;

    	if (videoCtl_g.wdrEnable)
    	{
    		funcInit.wdrMode = videoCtl_g.wdrMode;
    	}
    	else
    	{
    		funcInit.wdrMode = VIDEO_WDR_MODE_NONE;
    	}

    	ret = pVideoIsp->pFuncInit(pVideoIsp, &funcInit);
    	if (ret)
    	{
    		LOG_PrintError("pVideoIsp->pFuncInit failed!\n");
    		return -1;
    	}

    	ret = pVideoIsp->pFuncStart(pVideoIsp);
    	if (ret)
    	{
    		LOG_PrintError("pVideoIsp->pFuncStart failed!\n");
    		return -1;
    	}
	}

	return 0;
}

/*******************************************************************************
  Function:     VIDEO_MpiInit
  Description:  mpp初始化
  Input:        无
  Output:       无
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
int VIDEO_MpiInit(void)
{
    int s32Ret;

    /*s32Ret = VIDEO_IspInit();
	if (s32Ret)
	{
		LOG_PrintError("VIDEO_IspInit failed!\n");
		return -1;			
	}*/

    s32Ret = RK_MPI_SYS_Init();
    if (s32Ret)
    {
        LOG_PrintError("RK_MPI_SYS_Init faild with %#x!\n", s32Ret);
        return -1;
    }

    return 0;
}

/*******************************************************************************
  Function:     VIDEO_MppDeInit
  Description:  mpp注销
  Input:        无
  Output:       无
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
int VIDEO_MppDeInit(void)
{
    return 0;
}


/*******************************************************************************
  Function:     VIDEO_GetLenName
  Description:  获取镜头名
  Input:        无
  Output:       - pLenName: 镜头名
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
static int VIDEO_GetLenName(char *pLenName)
{
    unsigned int i;
    unsigned int fixLenNum = 0, lenNum = 0;
    cJSON *pItem, *pSubItem, *pLenNameItem;
    char fixLenTbl[8][32];
    char lenTbl[8][32];
    char (*pLenTbl)[32];

    pLenTbl = fixLenTbl;
    pItem = CFG_GetItem(NULL, "fixLenCfg");
    if (pItem)
    {
        fixLenNum = cJSON_GetArraySize(pItem);
        if (fixLenNum > 8)
        {
            fixLenNum = 8;
        }
         
        for (i=0; i<fixLenNum; i++)
        {
            pSubItem = cJSON_GetArrayItem(pItem, i);
            if (!pSubItem)
            {
                LOG_PrintError("Failed to get config zoomFocusCfg[%d]!\n", i);
                return -1;
            }

            pLenNameItem = CFG_GetItem(pSubItem, "lenName");
            if (!pLenNameItem)
            {
                LOG_PrintError("Failed to get config lenName!\n");
                return -1;
            }

            strncpy((char *)pLenTbl, pLenNameItem->valuestring, 32);
            pLenTbl++;
        }
    }

    pItem = CFG_GetItem(NULL, "motor");
    if (pItem)
    {
        pLenTbl = lenTbl;
        pItem = CFG_GetItem(NULL, "zoomFocusCfg");
        if (pItem)
        {
            lenNum = cJSON_GetArraySize(pItem);
            if (lenNum > 8)
            {
                lenNum = 8;
            }
             
            for (i=0; i<lenNum; i++)
            {
                pSubItem = cJSON_GetArrayItem(pItem, i);
                if (!pSubItem)
                {
                    LOG_PrintError("Failed to get config zoomFocusCfg[%d]!\n", i);
                    return -1;
                }

                pLenNameItem = CFG_GetItem(pSubItem, "lenName");
                if (!pLenNameItem)
                {
                    LOG_PrintError("Failed to get config lenName!\n");
                    return -1;
                }

                strncpy((char *)pLenTbl, pLenNameItem->valuestring, 32);
                pLenTbl++;
            }
        }
    }
    
    if (fixLenNum == 0 && lenNum == 0)
    {
        pLenName[0] = '\0';
        return 0;
    }
    
    pItem = CFG_GetItem(NULL, "lenName");
    if (pItem)
    { 
        strcpy(pLenName, pItem->valuestring);

        for (i=0; i<fixLenNum; i++)
        {
            if (strlen(pLenName) != strlen(fixLenTbl[i]))
            {
                continue;
            }

            if (strcmp(pLenName, fixLenTbl[i]))
            {
                continue;
            }

            return 0;
        }

        for (i=0; i<lenNum; i++)
        {
            if (strlen(pLenName) != strlen(lenTbl[i]))
            {
                continue;
            }

            if (strcmp(pLenName, lenTbl[i]))
            {
                continue;
            }

            return 0;
        }

        /* 配置的镜头参数无效使用默认镜头 */
        LOG_PrintWarn("lenName %s is invalid!\n", pLenName);
        if (fixLenNum > 0)
        {
            strcpy(pLenName, fixLenTbl[0]);
        }
        else
        {
            strcpy(pLenName, lenTbl[0]);
        }
    }
    else
    {
        if (fixLenNum > 0)
        {
            strcpy(pLenName, fixLenTbl[0]);
        }
        else
        {
            strcpy(pLenName, lenTbl[0]);
        }
    }

    return 0;
}


/*******************************************************************************
  Function:     VIDEO_GetLdrCfg
  Description:  获取Ldr模式
  Input:        无
  Output:       - pDayNightSwitchMask: ldr模式
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
static int VIDEO_GetLdrCfg(int *pDayNightSwitchMask)
{
    cJSON *pJson, *pSubItem;
    int ldrMode;
    
    /* 所有设备支持手动黑白和彩色 */
    *pDayNightSwitchMask = 
        (1<<videoDayNightSwitchColor) | (1<<videoDayNightSwitchBlack);

    /* 判断感觉值从外部获取还是从内部获取 */
    pJson = CFG_GetItem(NULL, "ldrCfg.mode");
    if (pJson)
    {

        ldrMode = pJson->valueint;
    }
    else
    {
        ldrMode = 0;
    }
        
    if (ldrMode == 0)
    {
        pJson = CFG_GetItem(NULL, "ldrCfg.type");
        if (pJson)
        { 
            if (pJson->valueint == 2) /* config配置存在，实际无光敏电阻 */
            {
                *pDayNightSwitchMask = (1<<videoDayNightSwitchColor
                                        | 1<<videoDayNightSwitchBlack
                                        | 1<<videoDayNightSwitchSensorDetect);
            }
        }
        else
        {
            pJson = CFG_GetItem(NULL, "ldr");
            if (pJson)
            {

                pSubItem = cJSON_GetObjectItem(pJson, "type");
                if (pSubItem)
                {
                    if (pSubItem->valueint == 1) /* AD模式光敏电阻，支持AD采样阈值切换 */
                    {
                        *pDayNightSwitchMask |= (1<<videoDayNightSwitchPhotoresistorThreshold);
                    }
                    else /* IO模式光敏电阻 */
                    {
                        *pDayNightSwitchMask |= (1<<videoDayNightSwitchPhotoresistor);
                        
                        if (videoCtl_g.smartIr) /* 同时支持smartIr时支持混合控制，即黑转彩是IO切换，彩转黑是sensor感光切换 */
                        {
                            *pDayNightSwitchMask |= (1<<videoDayNightSwitchMixture);
                        } 
                    }
                }
                else /* 获取不到类型是IO模式光敏 */
                {
                    *pDayNightSwitchMask |= (1<<videoDayNightSwitchPhotoresistor);
                    
                    if (videoCtl_g.smartIr) /* 同时支持smartIr时支持混合控制，即黑转彩是IO切换，彩转黑是sensor感光切换 */
                    {
                        *pDayNightSwitchMask |= (1<<videoDayNightSwitchMixture);
                    } 
                }
            }
            else /* 无光敏，sensor感光切换 */
            {
                *pDayNightSwitchMask |= (1<<videoDayNightSwitchSensorDetect);
            } 
        }
    }
    else
    {
        pJson = CFG_GetItem(NULL, "ldrCfg.type");
        if (!pJson)
        { 
            LOG_PrintError("Fail to get ldr type!\n");
            return -1; 
        }

        if (pJson->valueint == 0)   /* IO模式光敏 */
        {
            *pDayNightSwitchMask |= (1<<videoDayNightSwitchPhotoresistor);
            
            if (videoCtl_g.smartIr) /* 同时支持smartIr时支持混合控制，即黑转彩是IO切换，彩转黑是sensor感光切换 */
            {
                *pDayNightSwitchMask |= (1<<videoDayNightSwitchMixture);
            }
        }
        else    /* AD模式光敏 */
        {
            *pDayNightSwitchMask |= (1<<videoDayNightSwitchPhotoresistor);
        }
    }

    return 0;
}


/*******************************************************************************
  Function:     VIDEO_GetConfig
  Description:  获取配置信息
  Input:        无
  Output:       无
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
static int VIDEO_GetConfig(void)
{
    cJSON *pJson, *pSubItem;
    
    pJson = CFG_GetItem(NULL, "video");
    if (!pJson)
    {
        LOG_PrintError("Fail to get config video!\n");
        return -1; 
    }

    pSubItem = cJSON_GetObjectItem(pJson, "sensor");
    if (!pSubItem)
    {
        LOG_PrintError("Fail to get config sensor!\n");
        return -1; 
    }
    videoCtl_g.snsType = pSubItem->valueint;

    pSubItem = cJSON_GetObjectItem(pJson, "standard");
    if (!pSubItem)
    {
        LOG_PrintError("Fail to get config standard!\n");
        return -1; 
    }
    videoCtl_g.standard = pSubItem->valueint;

    videoCtl_g.wdrEnable = 0;

    pSubItem = cJSON_GetObjectItem(pJson, "resolution");
    if (!pSubItem)
    {
        LOG_PrintError("Fail to get config resolution!\n");
        return -1; 
    }
    videoCtl_g.maxResolution = videoCtl_g.resolution = VIDEO_RESOLUTION_H1080;//pSubItem->valueint;     

    pSubItem = cJSON_GetObjectItem(pJson, "fps");
    if (pSubItem)
    {
        videoCtl_g.maxFps = pSubItem->valueint;
    }

    pJson = CFG_GetItem(NULL, "videoOut");
    if (pJson)
    {
        videoCtl_g.videoOut = 1; 
    }
    else
    {
        videoCtl_g.videoOut = 0;
    }

    pJson = CFG_GetItem(NULL, "gyroscope");
    if (pJson)
    {
        videoCtl_g.supportDir = 1; 
    }
    else
    {
        videoCtl_g.supportDir = 0;
    }
    
    pJson = CFG_GetItem(NULL, "devInfo.hwid");
    if (pJson)
    {
        videoCtl_g.haveHwid = 1;
    }
    else
    {
        videoCtl_g.haveHwid = 0;
    }
    
#if 0
    int ret, num;
    cJSON *pJson, *pSubItem;
    SYS_devInfo_t devInfo;  
    int mode;
    char value[16]={0};     

    pJson = CFG_GetItem(NULL, "standard-custom");
    if (pJson)
    {
		videoCtl_g.standard = pJson->valueint;
    }
    else
    {
    	videoCtl_g.standard = VIDEO_STANDARD_NTSC;
    }

    /*ret = CFG_EnvGet("ispdebug", value, 16);
    if (!ret)
    {
        videoCtl_g.ispdebug = strtoul(value, NULL, 0);
    }*/
    videoCtl_g.ispdebug = 0;

    videoCtl_g.mirror = 0;
        
    pJson = CFG_GetItem(NULL, "video");
    if (!pJson)
    {
        LOG_PrintError("Fail to get config video!\n");
        return -1; 
    }
    
    pSubItem = cJSON_GetObjectItem(pJson, "sensor");
    if (!pSubItem)
    {
        LOG_PrintError("Fail to get config processor!\n");
        return -1; 
    }
    videoCtl_g.snsType = pSubItem->valueint;
    
	videoCtl_g.wdrEnable = 0;
	//videoCtl_g.wdrMode = VIDEO_WDR_MODE_2To1_LINE;

    pSubItem = cJSON_GetObjectItem(pJson, "resolution");
    if (!pSubItem)
    {
        LOG_PrintError("Fail to get config processor!\n");
        return -1; 
    }
    videoCtl_g.maxResolution = videoCtl_g.resolution = pSubItem->valueint;     

    pSubItem = cJSON_GetObjectItem(pJson, "fps");
    if (pSubItem)
    {
        videoCtl_g.maxFps = pSubItem->valueint;
    }

#if 0
    videoCtl_g.wideDynamicRange = 2;
    videoCtl_g.wdrEnable = 1;
    videoCtl_g.wdrMode = VIDEO_WDR_MODE_2To1_LINE;
#else
    videoCtl_g.wideDynamicRange = 1;
    videoCtl_g.wdrEnable = 0;
    videoCtl_g.wdrMode = VIDEO_WDR_MODE_NONE;
#endif
    pSubItem = cJSON_GetObjectItem(pJson, "wdr");
    if (!pSubItem)
    {
        videoCtl_g.wdrMode = VIDEO_WDR_MODE_NONE;
        videoCtl_g.wideDynamicRange = 1;
    }
    else
    {
        videoCtl_g.wdrMode = pSubItem->valueint;
        if (videoCtl_g.wdrMode)
        {
            videoCtl_g.wideDynamicRange = 2;
            videoCtl_g.wdrEnable = 1;
        }
        else
        {
            videoCtl_g.wideDynamicRange = 1;
        }
    }

    pSubItem = cJSON_GetObjectItem(pJson, "supportAvbr");
    if (!pSubItem)
    {
         videoCtl_g.supportAvbr = 1;
    }
    else
    {
        videoCtl_g.supportAvbr = pSubItem->valueint;
    }
    
    pJson = CFG_GetItem(NULL, "smartIR");
    if (!pJson)
    {
        LOG_PrintInfo("Fail to get config smartIr!\n");
        videoCtl_g.smartIr = 0; 
    }
    else
    { 
        videoCtl_g.smartIr = 1; 

		num = cJSON_GetArraySize(pJson);
		if (num == 2)
		{
	        videoCtl_g.smartIrMask = 
	            (1<<VideoSmartIrNear) | (1<<VideoSmartIrFar);
		}
		else
		{
		    videoCtl_g.smartIrMask = (1<<VideoSmartIrNear);
		}
		
        pJson = CFG_GetItem(NULL, "smartIrCaps.enable");
        if (pJson)
        {
            videoCtl_g.smartIr = pJson->valueint; 
        }

        pJson = CFG_GetItem(NULL, "smartIrCaps.mask");
        if (pJson)
        {
            videoCtl_g.smartIrMask = strtoul(pJson->valuestring, NULL, 0); 
        } 
    } 


    /*ret = VIDEO_GetLdrCfg(&videoCtl_g.dayNightSwitchMask);
    if (ret)
    {
        LOG_PrintError("Fail to get ldr cfg!\n");
        return -1; 
    }
    
    ret = VIDEO_GetLenName(videoCtl_g.lenName);
    if (ret)
    {
        LOG_PrintError("Fail to get len cfg!\n");
        return -1; 
    }*/

    pJson = CFG_GetItem(NULL, "softwareVer");
    if (pJson)
    { 
        videoCtl_g.softwareVer = atoi(pJson->valuestring);
    }

    pJson = CFG_GetItem(NULL, "devInfo.hwid");
    if (pJson)
    {
        videoCtl_g.haveHwid = 1;
    }
    else
    {
        videoCtl_g.haveHwid = 0;
    }

    /*pJson = CFG_GetItem(NULL, "videoCfg");
    if (pJson)
    { 
        pSubItem = cJSON_GetObjectItem(pJson, "fisheye");
        if (!pSubItem)
        {
            videoCtl_g.isFisheye = 0; 
        }
        else
        {
            videoCtl_g.isFisheye = pSubItem->valueint;
        }
    }

    
    pJson = CFG_GetItem(NULL, "videoCfg");
    if (pJson)
    {
        pSubItem = cJSON_GetObjectItem(pJson, "jpeg2rgbEnable");
        if (!pSubItem)
        {
            videoCtl_g.jpeg2RgbEn = 0;
        }
        else
        {
            videoCtl_g.jpeg2RgbEn = pSubItem->valueint;
        }

        pSubItem = cJSON_GetObjectItem(pJson, "maxWidth");
        if (!pSubItem)
        {
            videoCtl_g.jpegMaxWidth = 1280;
        }
        else
        {
            videoCtl_g.jpegMaxWidth = pSubItem->valueint;
        }

        pSubItem = cJSON_GetObjectItem(pJson, "maxHeight");
        if (!pSubItem)
        {
            videoCtl_g.jpegMaxHeight = 720;
        }
        else
        {
            videoCtl_g.jpegMaxHeight = pSubItem->valueint;
        }
    }*/

    /*ret = SYS_GetDevInfo(&devInfo);
    if (ret)
    {
        LOG_PrintError("Fail to get device infomation!\n");
        return -1; 
    }*/
    videoCtl_g.cpuType = SYS_CPU_RV1126;//devInfo.cpuType;

    /* P帧帧内刷新要多占CPU和内存，HI3516EV200平台强制不开启 */
    videoCtl_g.pIntraRefresh = 0;
    pJson = CFG_GetItem(NULL, "pIntraRefresh");
    if (pJson)
    {
        videoCtl_g.pIntraRefresh = pJson->valueint;
    }

    pJson = CFG_GetItem(NULL, "videoCfg.led");
    if (pJson)
    {
        pSubItem = cJSON_GetObjectItem(pJson, "gpioIndex");
        if (pSubItem)
        {
    	    videoCtl_g.ledGpio = pSubItem->valueint;
    	}
    	else
    	{
    	    LOG_PrintError("Fail to get led gpio.\n");
    	    return -1;
    	}
        
        pSubItem = cJSON_GetObjectItem((pJson), "gpioLevel");
        if (pSubItem)
        {
            videoCtl_g.ledLevel = pSubItem->valueint;
    	}
    	else
    	{
    	    LOG_PrintError("Fail to get led level.\n");
    	    return -1;
    	}
        
        GPIO_Get(videoCtl_g.ledGpio);
        GPIO_SetDir(videoCtl_g.ledGpio, 1);
        GPIO_SetLevel(videoCtl_g.ledGpio, !videoCtl_g.ledLevel); 
    }
    else
    {
        videoCtl_g.ledGpio = -1;
        videoCtl_g.ledLevel = -1;
    }

    /* 编码gop模式 */
    videoCtl_g.stGopAttr.enGopMode = VENC_GOPMODE_SMARTP;
    videoCtl_g.stGopAttr.stSmartP.u32BgInterval = 30;  
    videoCtl_g.stGopAttr.stSmartP.s32BgQpDelta = 7; 
    videoCtl_g.stGopAttr.stSmartP.s32ViQpDelta = 2; 
    
    pJson = CFG_GetItem(NULL, "advGop");
    if (!pJson)
    {
        goto out;
    }

    pSubItem = cJSON_GetObjectItem(pJson, "mode");
    if (!pSubItem)
    {
        goto out;
    }
    mode = pSubItem->valueint;
    
    switch (mode)
    {
        case VENC_GOPMODE_DUALP: 
            pSubItem = cJSON_GetObjectItem(pJson, "IPQpDelta");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stDualP.s32IPQpDelta = pSubItem->valueint;  

            pSubItem = cJSON_GetObjectItem(pJson, "SPInterval");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stDualP.u32SPInterval = pSubItem->valueint; 

            pSubItem = cJSON_GetObjectItem(pJson, "SPQpDelta");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stDualP.s32SPQpDelta = pSubItem->valueint; 

            videoCtl_g.stGopAttr.enGopMode = VENC_GOPMODE_DUALP;
            break;
        case VENC_GOPMODE_SMARTP: 
            pSubItem = cJSON_GetObjectItem(pJson, "BgInterval");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stSmartP.u32BgInterval = pSubItem->valueint;  

            pSubItem = cJSON_GetObjectItem(pJson, "BgQpDelta");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stSmartP.s32BgQpDelta = pSubItem->valueint; 

            pSubItem = cJSON_GetObjectItem(pJson, "ViQpDelta");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stSmartP.s32ViQpDelta = pSubItem->valueint; 

            videoCtl_g.stGopAttr.enGopMode = VENC_GOPMODE_SMARTP;
            break;
        case VENC_GOPMODE_BIPREDB: 
            pSubItem = cJSON_GetObjectItem(pJson, "IPQpDelta");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stBipredB.s32IPQpDelta = pSubItem->valueint;  

            pSubItem = cJSON_GetObjectItem(pJson, "BFrmNum");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stBipredB.u32BFrmNum = pSubItem->valueint; 

            pSubItem = cJSON_GetObjectItem(pJson, "BQpDelta");
            if (!pSubItem)
            {
                goto out;
            }
            videoCtl_g.stGopAttr.stBipredB.s32BQpDelta = pSubItem->valueint; 

            videoCtl_g.stGopAttr.enGopMode = VENC_GOPMODE_BIPREDB;
            break; 
        default: 
            goto out;
    } 

out:

    switch (videoCtl_g.cpuType)
    {
        case SYS_CPU_HI3559AV100:
        case SYS_CPU_HI3519AV100:
		case SYS_CPU_HI3516CV500:
		case SYS_CPU_HI3516EV200:
		case SYS_CPU_HI3516EV300:
		case SYS_CPU_HI3518EV300:
		case SYS_CPU_HI3516DV300:
            videoCtl_g.ldc = NO_LDC; 
            break;
        default:
            videoCtl_g.ldc = NO_LDC; 
            break;
    } 
    
    LOG_PrintInfo("snsType %d standard %d resolution %d cpuType %d!\n",
                    videoCtl_g.snsType,
                    videoCtl_g.standard,
                    videoCtl_g.resolution, 
                    videoCtl_g.cpuType);
#endif

    return 0;
}


/*******************************************************************************
  Function:     VIDEO_GetPerCfg
  Description:  获取视频相关配置
  Input:        无 
  Output:       无
  Return:       0:成功
                <0:失败
  Others:       无
*******************************************************************************/
int VIDEO_GetPerCfg(void)
{
	int ret;
	char key[32];
	int standard, resolution, wdrEnable;

	ret = INI_KeyGetInt(VIDEO_INI_CFG, "video", "resolution", &resolution);
	if (!ret)
	{
		if (videoCtl_g.resolution != resolution)
		{
			videoCtl_g.resolution = resolution;
		}
	}

	ret = INI_KeyGetInt(VIDEO_INI_CFG, "video", "standard", &standard);
	if (!ret)
	{
		if (videoCtl_g.standard != standard)
		{
			videoCtl_g.standard = standard;
		}
	}

	ret = INI_KeyGetInt(VIDEO_INI_CFG, "video", "wdrEnable", &wdrEnable);
	if (!ret)
	{
		if (videoCtl_g.wdrEnable != wdrEnable)
		{
			videoCtl_g.wdrEnable = wdrEnable;
		}
	}
	
	return 0;
}

int DIR_GetAngle(void)
{
    return videoCtl_g.dirAngle;
}

int SYS_CheckHwid(void)
{
    return videoCtl_g.haveHwid;
}

int DIR_GetFlip(void)
{
    return videoCtl_g.flip;
}

int SYS_SpeakerTest(void)
{
    return videoCtl_g.speakerTest;
}

int VIDEO_PlayStatus(void)
{
    return videoCtl_g.voStatus;
}

static void *VIDEO_DirThd(void *parg)
{
    int fd;
    int ret, i;
    int oldFlip = -1;
    DIR_cmdArgs_t dirCmdArgs;
    int vpssChn, vpssGrp = 0;
    int accelAbs;
    VIDEOISP_ctl_t *pVideoIsp;
    
    pVideoIsp = videoCtl_g.pVideoIsp;

    fd = open("/dev/"DIR_DEV_NAME, O_RDWR);
    if (fd < 0)
    {
        LOG_PrintError("open %s dev failed!\n", DIR_DEV_NAME);
        return NULL;
    }
    
    while (1)
    {
        ret = ioctl(fd, DIR_GET_ACCEL, &dirCmdArgs);
        if (ret < 0)
        {
            LOG_PrintError("Fail to ioctl get dir accel.\n");
            continue;
        }

        /*for (i = 0; i < 3; i++)
        {
            LOG_PrintInfo("accel_short[%d]:%d\n", i, dirCmdArgs.accel_short[i]);
        }*/

#if 1
        if (dirCmdArgs.accel_short[2] < -2048)
        {
            videoCtl_g.flip = 0;
        }
        else if (dirCmdArgs.accel_short[2] > 2048)
        {
            videoCtl_g.flip = 1;
        }

        accelAbs = abs(dirCmdArgs.accel_short[2]);
        if (accelAbs >= 16666)
        {
            videoCtl_g.dirAngle = 0;
        }
        else
        {
            videoCtl_g.dirAngle = (accelAbs/dirCmdArgs.accel_short[2])*(16666 - accelAbs)*90/16666;
        }
#else
        if (dirCmdArgs.accel_short[1] < -2048)
        {
            videoCtl_g.flip = 1;//0;
        }
        else if (dirCmdArgs.accel_short[1] > 2048)
        {
            videoCtl_g.flip = 0;//1;
        }

        accelAbs = abs(dirCmdArgs.accel_short[1]);
        if (accelAbs >= 16666)
        {
            videoCtl_g.dirAngle = 0;
        }
        else
        {
            videoCtl_g.dirAngle = (accelAbs/dirCmdArgs.accel_short[1])*(16666 - accelAbs)*90/16666;
        }
#endif
       
        if (oldFlip != videoCtl_g.flip)
        {
            oldFlip = videoCtl_g.flip;

            if (1 == videoCtl_g.mirrorCfg)
            {
                videoCtl_g.mirror = !videoCtl_g.flip;
            }
            else
            {
                videoCtl_g.mirror = videoCtl_g.flip;
            }

            if (pVideoIsp)
            {
                ret = pVideoIsp->pSetMirrorFlip(pVideoIsp, videoCtl_g.mirror, videoCtl_g.flip);
                if (ret)
                {
                    LOG_PrintError("Isp set mirror flip fail!!\n");
                }
            }
        }

        usleep(200*1000);
    }

    close(fd);

    return NULL;
}

static int VIDEO_Dir(void)
{
    int ret;
    pthread_t dirThd;
    
    ret = pthread_create(&dirThd, 0, VIDEO_DirThd, NULL);
    if (ret)
    {
        LOG_PrintError("can't create thread: %s\n", strerror(ret));
        return -1;
    }
    
    return 0;
}

static void *VIDEO_LedThd(void *parg)
{
    int level = 0;
    
    while (1)
    {
        if (0 == videoCtl_g.haveHwid)
        {
            level = !level;
            
            if (videoCtl_g.ledGpio >= 0)
            {
                GPIO_SetLevel(videoCtl_g.ledGpio, level);
            }
        }
        
        sleep(2);
    }
    
    return NULL;
}


static int VIDEO_LedTest(void)
{
    int ret;
    pthread_t ledThd;
    
    ret = pthread_create(&ledThd, 0, VIDEO_LedThd, NULL);
    if (ret)
    {
        LOG_PrintError("can't create thread: %s\n", strerror(ret));
        return -1;
    }
    
    return 0;
}

static int USB_CheckConnect(int *connState)
{
    char *pStr;
    FILE *fp = NULL;
    char buff[64] = {0};

    fp = fopen(USB_DWC3_PATH, "r");
    if(!fp)
    {
        LOG_PrintError("Fail to open %s.\n", USB_DWC3_PATH);
        return -1;
    }

    fread(buff, 1, 64, fp);

    pStr = strstr(buff, "cnt2host");
    if (pStr)
    {
        *connState = 1;
    }
    else
    {
        *connState = 0;
    }

    fclose(fp);
    
    return 0;
}

static void *VIDEO_CheckConnectThd(void *parg)
{
    int yellowLed = 70;
    int whiteLed = 53;
    int ledLevel = 1;
    int connState = 0, oldConnState = -1;
    
    while (1)
    {
        if (USB_CheckConnect(&connState) == 0)
        {
            if (connState != oldConnState)
            {
                oldConnState = connState;
                if (0 == connState)
                {
                    GPIO_SetLevel(yellowLed, ledLevel);
                    GPIO_SetLevel(whiteLed, !ledLevel);
                    if (videoCtl_g.ledGpio >= 0)
                    {
                        GPIO_SetLevel(videoCtl_g.ledGpio, !videoCtl_g.ledLevel);
                    }
                }
                else
                {
                    GPIO_SetLevel(yellowLed, !ledLevel);
                    GPIO_SetLevel(whiteLed, ledLevel);
                }
            }
        }

        usleep(500*1000);
    }
    
    return NULL;
}

static int ADCKEY_GetVal(void)
{
    int val;
    int enable = 0;
    char *pStr;
    FILE *fp = NULL;
    char buff[128] = {0};

    fp = fopen("/sys/bus/iio/devices/iio\:device0/in_voltage1_raw", "r");
    if(!fp)
    {
        LOG_PrintError("Fail to open /sys/bus/iio/devices/iio\:device0/in_voltage1_raw.\n");
        return -1;
    }

    fread(buff, 1, 128, fp);

    val = atoi(buff);
    if (val < 512)
    {
        enable = 1;
    }
    else
    {
        enable = 0;
    }

    fclose(fp);
    
    return enable;
}

static void *VIDEO_KeyThd(void *parg)
{
#if 1
    int keyCnt = 0;
    int level = 0;
    int keyGpio = 97;

    GPIO_Get(keyGpio);
    GPIO_SetDir(keyGpio, 0);
    
    while (1)
    {
        GPIO_GetLevel(keyGpio, &level);
        
        if (0 == level)//(ADCKEY_GetVal() == 1)
        {
            keyCnt++;
        }
        else
        {
            keyCnt = 0;
        }
        
        if (keyCnt == 4)
        {
            videoCtl_g.speakerTest = !videoCtl_g.speakerTest;
        }
        usleep(500*1000);
    }
#else
    int i, ret;
    int readIrq = 1;
    int level = 0;
    int keyGpio = 71;
    int keyLevel = 0;
    int ledLevel = 1;
    int delayCnt = 0;
    int yellowLed = 70;
    int whiteLed = 53;
    int redLed = 52;
    pthread_t checkThd;

    GPIO_Get(keyGpio);
    GPIO_SetDir(keyGpio, 0);
    GPIO_EnableInt(keyGpio, GPIO_INT_FALLING);

    GPIO_Get(yellowLed);
    GPIO_SetDir(yellowLed, 1);
    GPIO_Get(whiteLed);
    GPIO_SetDir(whiteLed, 1);
    GPIO_Get(redLed);
    GPIO_SetDir(redLed, 1);
    
    ret = pthread_create(&checkThd, 0, VIDEO_CheckConnectThd, NULL);
    if (ret)
    {
        LOG_PrintError("can't create thread: %s\n", strerror(ret));
        return -1;
    }
    
    while (1)
    {
        if (readIrq)
        {
            ret = GPIO_ReadIrq(keyGpio);
            if (!ret)
            {
                readIrq = 0;
            }
        }
        else
        {
            ret = GPIO_GetLevel(keyGpio, &level);
            if (ret)
            {
                readIrq = 1;
                delayCnt = 0;
                continue;
            }
            
            if (level == keyLevel)
            {
                delayCnt++;
            }
            else
            {
                if (delayCnt == 0)
                {
                    readIrq = 1;
                    continue;
                }
                
                if ((delayCnt < 5) && (0 == videoCtl_g.haveHwid))
                {
                    for (i = 0; i < 3; i++)
                    {
                        GPIO_SetLevel(yellowLed, !ledLevel);
                        GPIO_SetLevel(whiteLed, !ledLevel);
                        GPIO_SetLevel(redLed, !ledLevel);
                        usleep(300*1000);
                        GPIO_SetLevel(yellowLed, ledLevel);
                        GPIO_SetLevel(whiteLed, ledLevel);
                        GPIO_SetLevel(redLed, ledLevel);
                        usleep(300*1000);
                    }
                }

                readIrq = 1;
                delayCnt = 0;
            }

            if (delayCnt == 15)
            {
                if (1 == videoCtl_g.haveHwid)
                {
                    system("rm /mnt/mtd/Config/config.ini");
                    reboot(RB_AUTOBOOT);
                }
                else
                {
                    videoCtl_g.speakerTest = !videoCtl_g.speakerTest;
                }
            }

            usleep(100*1000);
        }
    }
#endif
    return NULL;
}


static int VIDEO_KeyTest(void)
{
    int ret;
    pthread_t keyThd;
    
    ret = pthread_create(&keyThd, 0, VIDEO_KeyThd, NULL);
    if (ret)
    {
        LOG_PrintError("can't create thread: %s\n", strerror(ret));
        return -1;
    }
    
    return 0;
}

/*******************************************************************************
  Function:     VIDEO_init
  Description:  video模块初始化
  Input:        无
  Output:       无
  Return:       0: 操作成功
                -1: 操作失败
  Others:       无
*******************************************************************************/
static int VIDEO_init(void)
{
    int ret;

    memset(&videoCtl_g, 0, sizeof(videoCtl_g));

    strcpy(videoCtl_g.ispDeviceName[0], "/dev/video0");

    /*ret = LOG_Init();
    if (ret)
    {
        LOG_PrintError("Fail to init log!\n");
        return -1;
    }*/
    
    /*ret = CFG_Init();
    if (ret)
    {
        LOG_PrintError("Fail to init cfg!\n");
        return -1;
    }*/

    LOG_Banner();

    ret = VIDEO_GetConfig();
    if (ret)
    {
        LOG_PrintError("Fail to get config!\n");
        return -1;
    }

    /*ret = VIDEO_GetPerCfg();
    if (ret)
    {
        LOG_PrintError("Fail to get ini config!\n");
        return -1;
    }*/

	if (VIDEO_STANDARD_PAL == videoCtl_g.standard)
	{
		videoCtl_g.fps = 25;
	}
	else if (VIDEO_STANDARD_NTSC == videoCtl_g.standard)
	{
		videoCtl_g.fps = 30;
	}
	else
	{
		LOG_PrintError("standard %d is invalid!\n", videoCtl_g.standard);
      	return -1;
	}

	if (videoCtl_g.maxFps) /* 非实时设备 */
	{
		videoCtl_g.fps = videoCtl_g.maxFps; 	
	}

    videoCtl_g.mjpegBufRate = 1;
    videoCtl_g.vencBufRate = 1;
    
    switch (videoCtl_g.snsType)
    {
        case VIDEO_BT1120_200W:
        case VIDEO_BT1120_100W:
        case VIDEO_BT1120_130W: 
            videoCtl_g.needIsp = 0;
            break;
        default:
            videoCtl_g.needIsp = 1;
    }

    ret = VIDEO_MpiInit();
    if (ret)
    {
        LOG_PrintError("VIDEO_MpiInit failed!\n");
        return -1;
    }

    videoCtl_g.ledGpio = -1;

    videoCtl_g.speakerTest = 0;

    if (videoCtl_g.supportDir)
    {
        VIDEO_Dir();
    }
    VIDEO_LedTest();
    //VIDEO_KeyTest();
        
    pthread_mutex_init(&videoCtl_g.videoMutex, NULL);
    pthread_mutex_init(&videoCtl_g.encodeMutex, NULL);
    pthread_mutex_init(&videoCtl_g.viMutex, NULL);
    pthread_mutex_init(&videoCtl_g.voMutex, NULL);
    pthread_mutex_init(&videoCtl_g.detectMutex, NULL);
    pthread_mutex_init(&videoCtl_g.analyserMutex, NULL);
    pthread_mutex_init(&videoCtl_g.flashMutex, NULL);
    pthread_mutex_init(&videoCtl_g.graphMutex, NULL);
    pthread_mutex_init(&videoCtl_g.jpeg2rgbMutex, NULL);

    for(int i= 0; i < VDEC_MAX_CHN_NUM; ++i)
    {
        pthread_mutex_init(&videoCtl_g.decodeMutex[i], NULL);
    }
    
    pthread_mutex_init(&videoCtl_g.cropLock, NULL);
    pthread_cond_init(&videoCtl_g.cropBlk, NULL);
    
    VIDEO_RegCmd();

    /* 根据最大像素来分配 */
    videoCtl_g.pTitleBuf = malloc(ENC_TITLE_BUF);
    if (!videoCtl_g.pTitleBuf)
    {
        LOG_PrintError("Fail to malloc title buffer!\n");
        return -1;
    }

    videoCtl_g.isRotate = 1;

    videoCtl_g.isDebug = 0;
    videoCtl_g.viChnNum = 2;

    LOG_PrintError("VIDEO_INIT success!\n");
    
    return 0;
}

int VIDEO_HdmioutControl(uint8_t cmd)
{
    LOG_PrintError("VIDEO_HdmioutControl cmd=%d\n", cmd);
    if(hdmioutFd_s < 0 || videoCtl_g.voStatus == 0)
    {
        LOG_PrintError("Fail to VIDEO_HdmioutControl.\n");
        return -1;
    }

    int ret = 0;
    LT9611_cmdArgs_t lt9611Args;

    if(cmd == 0)
    {
        ret = ioctl(hdmioutFd_s, LT9611_DISABLE_HDMI, &lt9611Args);
        if (ret < 0)
        {
            LOG_PrintError("Fail to ioctl get lt9611 args.\n");
        }

        LOG_PrintInfo("LT9611_DISABLE_HDMI success\n");
    }
    else if(cmd == 1)
    {
        ret = ioctl(hdmioutFd_s, LT9611_ENABLE_HDMI, &lt9611Args);
        if (ret < 0)
        {
            LOG_PrintError("Fail to ioctl get lt9611 args.\n");
        }
        LOG_PrintInfo("LT9611_ENABLE_HDMI success\n");
    }
    else if(cmd == 2)
    {
        ret = ioctl(hdmioutFd_s, LT9611_CEC_STANDBY, &lt9611Args);
        if (ret < 0)
        {
            LOG_PrintError("Fail to ioctl get lt9611 args.\n");
        }
        LOG_PrintInfo("LT9611_CEC_STANDBY success\n");
    }
    else if(cmd == 3)
    {
        ret = ioctl(hdmioutFd_s, LT9611_CEC_IMAGEON, &lt9611Args);
        if (ret < 0)
        {
            LOG_PrintError("Fail to ioctl get lt9611 args.\n");
        }
        LOG_PrintInfo("LT9611_CEC_IMAGEON success\n");
    }
    

    return 0;
}


static void *VIDEO_VoDetectThd(void *parg)
{
    LOG_PrintInfo("vo detect tid:%d \n", gettid());
    int ret = 0;
     int oldStatus = 0;
    LT9611_cmdArgs_t lt9611Args;
    int iOldLedStatus = 0;
    int iNewLedStatus = 0;

#ifdef HDMI_ENABLE
    /* open */
    hdmioutFd_s = open("/dev/"LT9611_DEV_NAME, O_RDWR);
    if (hdmioutFd_s < 0)
    {
        LOG_PrintError("open %s dev failed!\n", LT9611_DEV_NAME);
        return NULL;
    }

    /* select init */
    fd_set readset,bak_set  ;
    FD_ZERO(&bak_set);
    FD_SET(hdmioutFd_s, &bak_set);

    struct timeval  tm ;
    tm.tv_sec = 0;
    tm.tv_usec = 1000;
#else
    videoCtl_g.voStatus = 1;
#endif
    while(1)
    {
        /* led */
        iNewLedStatus  = ENC_LedIsShow();
        if(iNewLedStatus != iOldLedStatus)
        {
            /* change led status*/
            if (videoCtl_g.ledGpio >= 0)
            {
                if(1 == iNewLedStatus)
                {
                    /* led to show */
                    GPIO_SetLevel(videoCtl_g.ledGpio, videoCtl_g.ledLevel);
                }
                else
                {
                    /* led not to show */
                    GPIO_SetLevel(videoCtl_g.ledGpio, !videoCtl_g.ledLevel);
                }
            }

            iOldLedStatus = iNewLedStatus;
        }
#ifdef HDMI_ENABLE
        /* hdmi detect */
        readset = bak_set;

        ret = select(hdmioutFd_s + 1 , &readset, NULL, NULL, &tm );
        if(ret > 0)
        {
            if(FD_ISSET(hdmioutFd_s, &readset))
            {
                ret = ioctl(hdmioutFd_s, LT9611_GET_HDMI, &lt9611Args);
                if (ret < 0)
                {
                    LOG_PrintError("Fail to ioctl get lt9611 args.\n");
                    lt9611Args.hdmiStatus = 0;
                    continue;
                }

                if(lt9611Args.hdmiStatus != videoCtl_g.voStatus)
                {
                    LOG_PrintInfo("old-hdmiStatus:%d --> new-hdmiStatus:%d\n", videoCtl_g.voStatus,lt9611Args.hdmiStatus);
                    videoCtl_g.voStatus = lt9611Args.hdmiStatus;
                }

            }
        }
#endif
        usleep(500*1000);

    }
}

static int VIDEO_VoDisplayInit()
{
    VO_CHN_ATTR_S stVoAttr = {0};
    
    stVoAttr.pcDevNode = "/dev/dri/card0";
    stVoAttr.u32Width  = HDMI_WIDTH;
    stVoAttr.u32Height = HDMI_HEIGHT;
    stVoAttr.u16Fps    = 0;
    stVoAttr.u16Zpos   = 0;//u32Zpos;
    stVoAttr.stImgRect.s32X       = 0;
    stVoAttr.stImgRect.s32Y       = 0;
    stVoAttr.stImgRect.u32Width   = HDMI_WIDTH;
    stVoAttr.stImgRect.u32Height  = HDMI_HEIGHT;
    stVoAttr.stDispRect.s32X      = 0;
    stVoAttr.stDispRect.s32Y      = 0;
    stVoAttr.stDispRect.u32Width  = HDMI_WIDTH;
    stVoAttr.stDispRect.u32Height = HDMI_HEIGHT;
    stVoAttr.emPlaneType          = VO_PLANE_OVERLAY;
    stVoAttr.enImgType            = IMAGE_TYPE_NV12;

    int ret = RK_MPI_VO_CreateChn(0, &stVoAttr);
    if (ret)
    {
        LOG_PrintError("Create vo[0] failed! ret=%d\n", ret);
        return -1;
    }

    /* hdmi detect thread */
    ret = pthread_create(&(videoCtl_g.voDetectThd), NULL, VIDEO_VoDetectThd, NULL);
    if(ret)
    {
        LOG_PrintError("can't create thread: %s\n", strerror(ret));
        return -1;
    }

    LOG_PrintWarn("VIDEO_VoDisplayInit success\n");

    return ret;
}

static int VIDEO_CommposeInit()
{
    /*初始化拼接动作*/
    if(hasCreated_s == 0)
    {
        Compose_InitStreamCompose();
        hasCreated_s = 1;
    }

    return 0;
}

/*******************************************************************************
  Function:     IpcSystemInit
  Description:  
  Input:        无
  Output:       无
  Return:       无
  Others:       无
*******************************************************************************/
void IpcSystemInit(void)
{
    VIDEO_init();
#if 0
    AUDIO_Init();
#endif    

    VIDEO_VoDisplayInit();

    VIDEO_CommposeInit();
}


